package pg.util;

import pg.objetosbasicos.Camera;
import pg.objetosbasicos.CoordenadasBaricentrica;
import pg.objetosbasicos.Ponto;
import pg.objetosbasicos.Triangulo;
import pg.objetosbasicos.Vetor;

public class OperacoesBasicas {
		
	public static Vetor calcularV(Vetor v, Vetor n) {
		Vetor tempVet = new Vetor();
		float k = ((v.x*n.x)+(v.y*n.y)+(v.z*n.z))/((n.x*n.x)+(n.y*n.y)+(n.z*n.z));
		tempVet.x = v.x - (k*n.x);
		tempVet.y = v.y - (k*n.y);
		tempVet.z = v.z - (k*n.z);
		return tempVet;
	}
	
	public static Ponto mudarBase(Vetor v1, Vetor v2, Vetor v3, Ponto p1, Ponto p2) {
		Vetor tempVet;
		Ponto retVet = new Ponto();	
		tempVet = Ponto.subtrair(p1, p2);//MODIFICADO
		retVet.x = Vetor.produtoEscalar(v1, tempVet);
		retVet.y = Vetor.produtoEscalar(v2, tempVet);
		retVet.z = Vetor.produtoEscalar(v3, tempVet);
		return retVet;
	}
	
	// TODO: VERIFICAR ESSE METODO
	public static CoordenadasBaricentrica calcularCoordenadasBaricentricas(Triangulo triangulo, Ponto ponto, Ponto[] pontos) {
		CoordenadasBaricentrica coordBaric = new CoordenadasBaricentrica();
		//Ponto p = ponto;
		Ponto p1 = pontos[triangulo.vertice1];
		Ponto p2 = pontos[triangulo.vertice2];
		Ponto p3 = pontos[triangulo.vertice3];

		float s;
		s = calcularAreaTriangulo(p1, p2, p3);
		coordBaric.alfa = calcularAreaTriangulo(ponto, p2, p3) / s;
		coordBaric.beta = calcularAreaTriangulo(p1, ponto, p3) / s;
		coordBaric.gama = calcularAreaTriangulo(p1, p2, ponto) / s;
		return coordBaric;
	}
	
	// TODO: VERIFICAR ESSE METODO
	public static float calcularAreaTriangulo(Ponto A, Ponto B, Ponto C) {
		return ((A.x*C.y - A.y*C.x + A.y*B.x - A.x*B.y + C.x*B.y - C.y*B.x) / 2);
	}

	public static Ponto projecaoPerspectiva(Ponto p, float d, float hx, float hy) {
		Ponto temp = new Ponto();
		temp.x = (d / hx) * (p.x / p.z);
		temp.y = (d / hy) * (p.y / p.z);
		temp.z = p.z;
		return temp;

	}

	public static Ponto CoordenadaTela(int resX, int resY, Ponto ponto) {
		Ponto retorno = new Ponto();
		retorno.x = (float)(Math.floor(((ponto.x+1)/2)*resX+0.5));
		retorno.y = (float)(Math.floor(resY-((ponto.y+1)/2)*resY+0.5));
		retorno.z = ponto.z;
		return retorno;
	}
	
	// TODO: VER ESSE METODO
	public static Vetor[] calcularNormalVertices(Triangulo[] triangulos, Vetor[] normaisTriangulos) {	
		int nTriangulos = triangulos.length;
		Vetor[] listaNormalPonto = new Vetor[3*nTriangulos];
		for(int i = 0; i< nTriangulos; i++) {
			listaNormalPonto[triangulos[i].vertice1].x += normaisTriangulos[i].x;
			listaNormalPonto[triangulos[i].vertice1].y += normaisTriangulos[i].y;
			listaNormalPonto[triangulos[i].vertice1].z += normaisTriangulos[i].z;

			listaNormalPonto[triangulos[i].vertice2].x += normaisTriangulos[i].x;
			listaNormalPonto[triangulos[i].vertice2].y += normaisTriangulos[i].y;
			listaNormalPonto[triangulos[i].vertice2].z += normaisTriangulos[i].z;

			listaNormalPonto[triangulos[i].vertice3].x += normaisTriangulos[i].x;
			listaNormalPonto[triangulos[i].vertice3].y += normaisTriangulos[i].y;
			listaNormalPonto[triangulos[i].vertice3].z += normaisTriangulos[i].z;	
		}
		for(int i = 0; i < 3*nTriangulos; i++) {
			listaNormalPonto[i].normalizar();// = Vetor.normalizar(listaNormalPonto[i]);
		}
		return listaNormalPonto;
	}
	
	// TODO: VER ESSE METODO
	public static Vetor[] calcularNormalTriangulos(Triangulo[] triangulos, Ponto[] listaPontos) {
		Ponto p1;
		Ponto p2;
		Ponto p3;

		Vetor v12;
		Vetor v13;
		
		Vetor vetNormal1;
					
		int length = triangulos.length;
		Vetor[] vetNormalTriangulo = new Vetor[length];

		for(int i = 0; i < length; i++) {
			p1 = listaPontos[triangulos[i].vertice1];
			p2 = listaPontos[triangulos[i].vertice2];
			p3 = listaPontos[triangulos[i].vertice3];

			v12 = Ponto.subtrair(p1,p2);
			v13 = Ponto.subtrair(p1,p3);
			
			vetNormal1 = Vetor.produtoVetorial(v12, v13);
			vetNormal1.normalizar();// = Vetor.normalizar(vetNormal1);

			vetNormalTriangulo[i].x = vetNormal1.x;
			vetNormalTriangulo[i].y = vetNormal1.y;
			vetNormalTriangulo[i].z = vetNormal1.z;
		}

		return vetNormalTriangulo;
	}
	
	public static Camera initCamera(Vetor v, Vetor n, Ponto c, float hx, float hy, float d) {
		Camera result = new Camera();
		result.c = c;
		result.v = calcularV(v,n);
		result.n = Vetor.normalizar(n);
		result.v.normalizar();// = Vetor.normalizar(result.v);
		result.u = Vetor.produtoVetorial(result.n,result.v);
		result.hx = hx;
		result.hy = hy;
		result.d = d;			
		return result;
	}
}
